using System.Collections.Specialized;
using System.Xml;
using SharpObjects.Interfaces;
using SharpObjects.Configuration;
using SharpObjects.Configuration.ConfigurationProviders;

namespace SharpObjects.Logging
{
	public class OriginFilter : IOriginFilter, IXmlInitializable
	{
		public class Patterns
		{
			public StringCollection StartsWith = null;
			public StringCollection Contains = null;
			public StringCollection EndsWith = null;

			public bool IsEmpty = true;

			public void AddStartsWith(string pattern)
			{
				if(StartsWith == null)
				{
					StartsWith = new StringCollection();
					IsEmpty = false;
				}

				StartsWith.Add(pattern);
			}

			public void AddStartsWith(string [] patterns)
			{
				foreach(string pattern in patterns)
				{
					AddStartsWith(pattern);
				}
			}

			public void AddContains(string pattern)
			{
				if(Contains == null)
				{
					Contains = new StringCollection();
					IsEmpty = false;
				}

				Contains.Add(pattern);
			}

			public void AddContains(string [] patterns)
			{
				foreach(string pattern in patterns)
				{
					AddContains(pattern);
				}
			}

			public void AddEndsWith(string pattern)
			{
				if(EndsWith == null)
				{
					EndsWith = new StringCollection();
					IsEmpty = false;
				}

				EndsWith.Add(pattern);
			}

			public void AddEndsWith(string [] patterns)
			{
				foreach(string pattern in patterns)
				{
					AddEndsWith(pattern);
				}
			}

			public void Clear()
			{
				if(StartsWith != null)
				{
					StartsWith.Clear();
				}

				if(Contains != null)
				{
					Contains.Clear();
				}

				if(EndsWith != null)
				{
					EndsWith.Clear();
				}
			}
		}

		public Patterns Include = new Patterns();
		public Patterns Exclude = new Patterns();


		public bool Pass(string origin)
		{

			bool includeMatches = false;

			if(! this.Include.IsEmpty)
			{
				if(! includeMatches && this.Include.StartsWith != null)
				{
					int count = this.Include.StartsWith.Count;

					for(int k = 0; k < count; k++)
					{
						if(origin.StartsWith(this.Include.StartsWith[k]))
						{
							includeMatches = true;
							break;
						}
					}
				}

				if(! includeMatches && this.Include.EndsWith != null)
				{
					int count = this.Include.EndsWith.Count;

					for(int k = 0; k < count; k++)
					{
						if(origin.EndsWith(this.Include.EndsWith[k]))
						{
							includeMatches = true;
							break;
						}
					}
				}

				if(! includeMatches && this.Include.Contains != null)
				{
					int count = this.Include.Contains.Count;

					for(int k = 0; k < count; k++)
					{
						if(origin.IndexOf(this.Include.Contains[k]) >= 0)
						{
							includeMatches = true;
							break;
						}
					}
				}
			}
			else
			{
				includeMatches = true;
			}

			if(includeMatches)
			{	
				if(! this.Exclude.IsEmpty)
				{
					bool excludeMatches = false;

					if(! excludeMatches && this.Exclude.StartsWith != null)
					{
						int count = this.Exclude.StartsWith.Count;

						for(int k = 0; k < count; k++)
						{
							if(origin.StartsWith(this.Exclude.StartsWith[k]))
							{
								excludeMatches = true;
								break;
							}
						}
					}

					if(! excludeMatches && this.Exclude.EndsWith != null)
					{
						int count = this.Exclude.EndsWith.Count;

						for(int k = 0; k < count; k++)
						{
							if(origin.EndsWith(this.Exclude.EndsWith[k]))
							{
								excludeMatches = true;
								break;
							}
						}
					}

					if(! excludeMatches && this.Exclude.Contains != null)
					{
						int count = this.Exclude.Contains.Count;

						for(int k = 0; k < count; k++)
						{
							if(origin.IndexOf(this.Exclude.Contains[k]) >= 0)
							{
								excludeMatches = true;
								break;
							}
						}
					}

					if(excludeMatches)
					{
						return false;
					}
					else
					{
						return true;
					}
				}
				else
				{
					return true;
				}
			}
			else
			{
				return false;
			}

		}



		public void Initialize(XmlElement initializationElement)
		{
			this.Include.Clear();
			this.Exclude.Clear();

			IConfigurationProvider config = new XmlConfigurationProvider(initializationElement);
			
			string [] patterns;
			
			patterns = config.GetStrings("include/starts_with");

			if(patterns != null && patterns.Length > 0)
			{
				this.Include.AddStartsWith(patterns);
			}

			patterns = config.GetStrings("include/contains");

			if(patterns != null && patterns.Length > 0)
			{
				this.Include.AddContains(patterns);
			}

			patterns = config.GetStrings("include/ends_with");

			if(patterns != null && patterns.Length > 0)
			{
				this.Include.AddEndsWith(patterns);
			}

			
			patterns = config.GetStrings("exclude/starts_with");

			if(patterns != null && patterns.Length > 0)
			{
				this.Exclude.AddStartsWith(patterns);
			}

			patterns = config.GetStrings("exclude/contains");

			if(patterns != null && patterns.Length > 0)
			{
				this.Exclude.AddContains(patterns);
			}

			patterns = config.GetStrings("exclude/ends_with");

			if(patterns != null && patterns.Length > 0)
			{
				this.Exclude.AddEndsWith(patterns);
			}

            this.IsInitialized = true;
        }

        public bool IsInitialized { get; set; }



		//#endregion
	}
}
